﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using WeiboSharp.Authenticators;
using WeiboSharp.Authenticators.OAuth;
using WeiboSharp.Extensions;
using WeiboSharp.Models;
using WeiboSharp.Web;

namespace WeiboSharp
{
    public partial class WeiboClient
    {
        public string BaseUrl { get; set; }
        public OAuth1Authenticator Credentials { get; set; }
        public bool FollowRedirects { get; set; }
        public int? MaxRedirects { get; set; }
        public string UserAgent { get; set; }
        public int Timeout { get; set; }
        public IWebProxy Proxy { get; set; }

        private WeiboRequest AuthenticateIfNeeded(WeiboRequest request)
        {
            return Credentials != null ? Credentials.Authenticate(this, request) : request;
        }

        private IHttp ConfigureHttp(WeiboRequest request, IHttp http)
        {
            http.Url = BuildUri(request);

            if (!string.IsNullOrWhiteSpace(UserAgent))
            {
                http.UserAgent = UserAgent;
            }

            http.Timeout = request.Timeout == 0 ? Timeout : request.Timeout;

            http.FollowRedirects = FollowRedirects;

            http.MaxRedirects = MaxRedirects;

            http.Headers.AddRange(request.Parameters.Where(t => t.Type == ParameterType.HttpHeader));

            http.Parameters.AddRange(request.Parameters.Where(t => t.Type == ParameterType.GetOrPost));

            if (Credentials.ParameterHandling == OAuthParameterHandling.UrlOrPostParameters)
            {
                http.Parameters.AddRange(request.Parameters.Where(t => t.Type == ParameterType.OAuth));
            }

            http.Files.AddRange(request.Files);

            //var body = (from p in request.Parameters
            //            where p.Type == ParameterType.RequestBody
            //            select p).FirstOrDefault();

            //if (body != null)
            //{
            //    http.RequestBody = body.Value.ToString();
            //    http.RequestContentType = body.Name;
            //}
            return http;
        }

        private IHttp ConfigureProxy(IHttp http)
        {
            if (Proxy != null)
            {
                http.Proxy = Proxy;
            }
            return http;
        }

        public Uri BuildUri(WeiboRequest request)
        {

            var assembled = string.Format("{0}/{1}", BaseUrl, request.Path);

            if (request.Method != WebMethod.Post && request.Method != WebMethod.Put)
            {
                Func<Parameter, bool> func;
                if (Credentials.ParameterHandling == OAuthParameterHandling.UrlOrPostParameters)
                {
                    func =
                        t => t.Type == ParameterType.GetOrPost || t.Type == ParameterType.OAuth;

                }
                else
                {
                    func =
                        t => t.Type == ParameterType.GetOrPost;
                }
                if (request.Parameters.Any(func))
                {
                    var parameters = request.Parameters.Where(func);
                    if (assembled.EndsWith("/"))
                    {
                        assembled = assembled.Substring(0, assembled.Length - 1);
                    }
                    string data = EncodeParameters(parameters);
                    assembled = string.Format("{0}?{1}", assembled, data);
                }
            }

            return new Uri(assembled);
        }

        private string EncodeParameters(IEnumerable<Parameter> parameters)
        {
            var querystring = new StringBuilder();
            foreach (var p in parameters)
            {
                if (querystring.Length > 1)
                    querystring.Append("&");
                querystring.AppendFormat("{0}={1}", p.Name.UrlEncode(), (p.Value).UrlEncode());
            }

            return querystring.ToString();
        }
    }
}
